<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>节流函数</title>
    <style>
        body {
            margin: 0;
        }

        .box {
            height: 200px;
            background: #000;
            color: white;
            text-align: center;
            line-height: 200px;
        }

        button {
            margin: auto;
            margin-top: 20px;
            display: block;
        }
    </style>
</head>

<body>
    <div class="box"></div>
    <!-- <button>取消节流</button> -->
</body>
<script>
    // 节流函数
    // function jl(fn, wait) {
    //     let last = 0;
    //     return function () {
    //         var now = Date.now();
    //         if (now - last > wait) {
    //             fn.apply(this, arguments);
    //             last = now;
    //         }
    //     }
    // }

    // 第一次会触发，最后一次不会触发函数
    // 不顾头，顾尾
    function throttle(func, wait) {
        let context, args;
        // 旧的时间戳
        let old = 0;
        return function () {
            context = this;
            args = arguments;
            // 获取当前的时间戳
            let now = new Date().valueOf();
            if (now - old > wait) {
                // 立即执行
                func.apply(context, args);
                old = now;
            }
        }
    }

    // 第一次不会触发，最后一次会触发函数
    // 顾头，不顾尾
    function throttle(func, wait) {
        let context, args, timeout;
        return function () {
            context = this;
            args = arguments;
            if (!timeout) {
                timeout = setTimeout(function () {
                    timeout = null;
                    func.apply(context, args);
                }, wait);
            }
        }
    }

    // 第一次直接触发，最后一次也会触发函数
    // 有头，也有尾
    function throttle(func, wait) {
        let context, args, timeout;
        let old = 0;
        let later = function () {
            old = new Date().valueOf();
            timeout = null;
            func.apply(context, args);
        }
        return function () {
            context = this;
            args = arguments;
            let now = new Date().valueOf();
            if (now - old > wait) {
                if (timeout) {
                    clearTimeout(timeout);
                    timeout = null;
                }
                func.apply(context, args);
                old = now;
            } else if (!timeout) {
                timeout = setTimeout(later, wait);
            }
        }
    }

    function throttle(func, wait, options = {}) {
        let context, args, timeout;
        let old = 0;
        let later = function () {
            old = new Date().valueOf();
            timeout = null;
            func.apply(context, args);
        }
        return function () {
            context = this;
            args = arguments;
            let now = new Date().valueOf();
            if (options.leading === false && !old) {
                old = now;
            }
            if (now - old > wait) {
                // 第一次会直接执行
                if (timeout) {
                    clearTimeout(timeout);
                    timeout = null;
                }
                func.apply(context, args);
                old = now;
            } else if (!timeout && options.trailing !== false) {
                // 最后一次也会被执行
                timeout = setTimeout(later, wait);
            }
        }
    }

    var box = document.querySelector('.box');
    box.onmousemove = throttle(move, 2000, {
        leading: true,
        trailing: false
    });

    function move(ev) {
        this.innerHTML = ev.clientX;
    }

</script>

</html>